
#include <iostream>
#include <string>
#include <cstring>
#include <stdint.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <set>
#include "log.hpp"
#include <functional>
#include "Task.hpp"
#include "Thread_Poll.hpp"

using namespace Logspace;

enum
{
    Sockfd_Err = 1,
    Bind_Err

};

const std::string defaultip = "0.0.0.0";
// 编写Udp服务器
class Server
{
    bool IsNewMember(const std::string& ip ,const sockaddr_in &client)
    {
        if(all_client_.count(ip)) return false;

        all_client_[ip] = client;
        return true;
    }

public:
    Server(uint16_t port, const std::string &ip = defaultip)
        : port_(port), ip_(ip), sockfd_(-1), isrunning_(false)
    {
    }

    void Start()
    {
        std::unique_ptr<thread_poll<Task>> &tp_ = thread_poll<Task>::GetInstance();
        tp_->run();

        isrunning_ = true;
        // 创建套接字
        sockfd_ = socket(AF_INET, SOCK_DGRAM, 0);
        if (sockfd_ < 0)
        {
            Log(Fatal) << "socket failed";
            exit(Sockfd_Err);
        }
        // bind绑定

        struct sockaddr_in local;
        memset(&local, 0, sizeof(local));
        local.sin_family = AF_INET;
        local.sin_port = htons(port_);
        inet_aton(ip_.c_str(), &(local.sin_addr));

        if (bind(sockfd_, (sockaddr *)&local, sizeof(local)) < 0)
        {
            Log(Fatal) << "bind failed";
            exit(Bind_Err);
        }

        Log(Info) << "bind success , the server is running";

        // while循环的接收任务
        while (1)
        {
            struct sockaddr_in client;
            std::string message = Recv(&client);
            std::string ip = inet_ntoa(client.sin_addr);

            if (IsNewMember(ip , client))
            {
                Log(Info) << "Welcome New Member : " << ip;
            }
            message = ip + " say : " + message;
            Task task(sockfd_, message, all_client_);
            tp_->push(task);
        }
    }

    ~Server()
    {
        if (isrunning_)
            close(sockfd_);
    }

    std::string Recv(struct sockaddr_in *pclient)
    {
        char buffer[1024];
        socklen_t len = sizeof(*pclient);
        int n = recvfrom(sockfd_, buffer, sizeof(buffer) - 1, 0, (sockaddr *)pclient, &len);
        if (n > 0)
            buffer[n] = 0;

        return buffer;
    }

private:
    uint16_t port_;  // 保存服务端端口号
    std::string ip_; // 保存服务端IP
    int sockfd_;     // 网络文件描述符
    bool isrunning_;
    std::unordered_map<std::string, sockaddr_in> all_client_;
};